package provider.gatewayWithSentinel;

import java.util.HashMap;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import libra.model.JsonResult;
import provider.gateway.BaseController;

/**
 * Gateway 整合 Sentinel 的测试控制器
 * @author libra
 */
@RestController
@RequestMapping("gatewayWithSentinel")
public class GatewayWithSentinelController extends BaseController {
	@Value( "#{'${server.servlet.context-path}'.concat('[port(${server.port})]')}" )
	String identity;
	
	private JsonResult<Object> buildSuccResp( Object obj ){
		return new JsonResult<Object>(0, identity, obj);
	}
	
	/*****************************************************/
	/***** 测试Gateway整合Sentinel的“针对请求属性”配置 *****/
	/*****************************************************/
	/**
	 * 测试Gateway整合Sentinel的"流控规则"->"针对请求属性"->"Client IP"
	 */
	@RequestMapping("clientIp")
	public Object clientIp( HttpServletRequest req ) throws Exception{
		return buildSuccResp( new HashMap<>() {{
			put("IP地址", getIpAddress(req));
		}} );
	}
	
	/**
	 * 测试Gateway整合Sentinel的"流控规则"->"针对请求属性"->"Header"
	 */
	@RequestMapping("header")
	public Object header( HttpServletRequest req ) throws Exception{
		return buildSuccResp( new HashMap<>() {{
			put("allHeaders", getAllHeaders(req));
		}} );
	}
	
	/**
	 * 测试Gateway整合Sentinel的"流控规则"->"针对请求属性"->"URL参数"
	 */
	@RequestMapping("param")
	public Object param( HttpServletRequest req ) throws Exception{
		return buildSuccResp( new HashMap<>() {{
			put("allParams", getAllParams(req));
		}} );
	}
	
	/**
	 * 测试Gateway整合Sentinel的"流控规则"->"针对请求属性"->"Cookie"
	 */
	@RequestMapping("cookie")
	public Object cookie( HttpServletRequest req ) throws Exception{
		return buildSuccResp( new HashMap<>() {{
			put("allCookies", getAllCookies(req));
		}} );
	}
	
	/**
	 * 测试Gateway整合Sentinel的"流控规则"->"针对请求属性"->"Remote Host"
	 */
	@RequestMapping("remoteHost")
	public Object remoteHost( HttpServletRequest req ) throws Exception{
		return buildSuccResp("remoteHost");
	}
	
	
	
	
	/************************************************/
	/***** 测试Gateway整合Sentinel的“API分组”配置 *****/
	/************************************************/
	/**
	 * 测试API分组中的【精确匹配】：group/exact/1、group/exact/2、group/exact/3
	 * 测试案例：
	 *     为接口 group/exact/1、group/exact/2 以“精确匹配”模式创建一个API分组，并在流控规则中为其设置1次/2s的QPS。
	 *     频繁访问 group/exact/1、group/exact/2、group/exact/3 接口，
	 *     其中 group/exact/1、group/exact/2 接口由于处在配置了流控规则的分组中，因此会受流控规则限制。
	 *     而 group/exact/3 接口不属于其中，所以访问不收任何限制。
	 */
	@RequestMapping("group/exact/1")
	public Object group_exact_1( HttpServletRequest req ) throws Exception{
		return buildSuccResp( "API分组【精确分组】：group_exact_1" );
	}
	@RequestMapping("group/exact/2")
	public Object group_exact_2( HttpServletRequest req ) throws Exception{
		return buildSuccResp( "API分组【精确分组】：group_exact_2" );
	}
	@RequestMapping("group/exact/3")
	public Object group_exact_3( HttpServletRequest req ) throws Exception{
		return buildSuccResp( "API分组【精确分组】：group_exact_3" );
	}
	
	
	/**
	 * 测试API分组中的【前缀匹配】：group/prefix/a/1、group/prefix/a/2、group/prefix/b、group/prefix/c、group/prefix/c
	 * 在API分组中，匹配串必须是以 "/*" 或者 "/**" 结尾，其中 "/*" 表示有且仅匹配一级请求路径， "/**" 表示匹配多级请求路径
	 * 测试案例：
	 *     新建API分组，并设置匹配规则
	 *     		group/prefix/a/*
	 *     		group/prefix/b
	 *     		group/prefix/c/*
	 *     		group/prefix/d/**
	 *    设置QPS【1次/2s】的分组流控，分别频繁访问 /group/prefix/[a、b、c、d] [/一级请求路径] [/多级请求路径]。
	 *    查看返回结果【 正常、404、流控 】
	 */
	@RequestMapping("group/prefix/a/1")
	public Object group_prefix_a_1( HttpServletRequest req ) throws Exception{
		return buildSuccResp( "API分组【前缀分组】：group_prefix_a_1" );
	}
	@RequestMapping("group/prefix/a/2")
	public Object group_prefix_a_2( HttpServletRequest req ) throws Exception{
		return buildSuccResp( "API分组【前缀分组】：group_prefix_a_2" );
	}
	@RequestMapping("group/prefix/b")
	public Object group_prefix_b( HttpServletRequest req ) throws Exception{
		return buildSuccResp( "API分组【前缀分组】：group_prefix_b" );
	}
	@RequestMapping("group/prefix/c")
	public Object group_prefix_c( HttpServletRequest req ) throws Exception{
		return buildSuccResp( "API分组【前缀分组】：group_prefix_c" );
	}
	@RequestMapping("group/prefix/d")
	public Object group_prefix_d( HttpServletRequest req ) throws Exception{
		return buildSuccResp( "API分组【前缀分组】：group_prefix_d" );
	}
	
	
	/**
	 * 测试API分组中的【正则匹配】：group/regular/11/aa、group/regular/22/bb、group/regular/cc/33、
	 */
	@RequestMapping("group/regular/11/aa")
	public Object group_regular_1_a( HttpServletRequest req ) throws Exception{
		return buildSuccResp( "API分组【正则分组】：group_regular_11_aa" );
	}
	@RequestMapping("group/regular/22/bb")
	public Object group_regular_2_b( HttpServletRequest req ) throws Exception{
		return buildSuccResp( "API分组【正则分组】：group_regular_22_bb" );
	}
	@RequestMapping("group/regular/cc/33")
	public Object group_regular_c_3( HttpServletRequest req ) throws Exception{
		return buildSuccResp( "API分组【正则分组】：group_regular_cc_33" );
	}
	
	
	
	
	/************************************************/
	/***** 测试Gateway整合Sentinel的“熔断、降级” *****/
	/************************************************/
	/**
	 * degrade_slowReqRatio、degrade_errorRatio、degrade_errorCount 三个接口分别以API分组的形式，配置熔断规则进行测试
	 */
	// "慢调用比例"测试
	@RequestMapping("degrade/slowReqRatio")
	public Object degrade_slowReqRatio( Boolean isSlow, HttpServletRequest req ) throws Exception{
		if( isSlow ) 
			Thread.sleep(500);
		return buildSuccResp( "熔断降级测试_DegradeSlowReqRatio(慢调用比例)" );
	}
	// "异常比例"测试
	@RequestMapping("degrade/errorRatio")
	public Object degrade_errorRatio( Boolean isError, HttpServletRequest req ) {
		int i = 1/(isError?0:1);
		return buildSuccResp( "熔断降级测试_DegradeErrorRatio(异常比例)" );
	}
	// "异常数"测试
	@RequestMapping("degrade/errorCount")
	public Object degrade_errorCount( HttpServletRequest req ) throws Exception{
		return buildSuccResp( "熔断降级测试_DegradeErrorCount(异常数)" );
	}
}
